const Koa = require('koa')
const app = new Koa()
const json = require('koa-json')
const onerror = require('koa-onerror')
const bodyparser = require('koa-bodyparser')
const logger = require('koa-logger')
const session = require('koa-session')
const compress = require('koa-compress')

//jwt令牌机制
// const koajwt = require('koa-jwt');

const util = require('util');
const cc = require('./conCtl')
const db = require('./dbCtl');
const js = require('./jsCtl')
const conf = require('./config.json');
require('./websocket.js');

// error handler
onerror(app)

//项目使用 pm2 set pm2-logrotate:retain 10 方式分割日志
// /* 日志搬运 ******************************************************************************************/
// const schedule = require('node-schedule')
// const fs = require('fs')
// const moment = require('moment')
// schedule.scheduleJob({
//     hour: 0,
//     minute: 3,
// }, () => {
//     const dir = moment().format('YYYY-MM-DD-HH-mm')
//     console.log('日志更新了')
//     fs.mkdir(`./logs/${dir}`, () => {
//         ['out', 'err', 'errfile'].map(itm => {
//             const readerStream = fs.createReadStream(`./logs/log.${itm}`);
//             let data = '';
//             readerStream.setEncoding('UTF8');
//             readerStream.on('data', chunk => data += chunk);
//             readerStream.on('end', () => {
//                 let writerStream = fs.createWriteStream(`./logs/${dir}/log.${itm}`);
//                 writerStream.write(data, 'UTF8');
//                 writerStream.end();
//                 writerStream.on('finish', () => {
//                     writerStream = fs.createWriteStream(`./logs/log.${itm}`);
//                     writerStream.write('');
//                     writerStream.end();
//                 });
//             });
//         })
//     })
// })

// middlewares
app.use(bodyparser({
  enableTypes: ['json', 'form', 'text']
}))
app.use(json())
app.use(logger())

//压缩设置
app.use(
  compress({
    filter: function (content_type) { // 只有在请求的content-type中有gzip类型，我们才会考虑压缩，因为zlib是压缩成gzip类型的
      return /text/i.test(content_type);
    },
    threshold: 1024, // 阀值，当数据超过1kb的时候，可以压缩
    flush: require('zlib').Z_SYNC_FLUSH // zlib是node的压缩模块
  })
);

const CONFIG = {
  /**  cookie的key。 (默认是 koa:sess) */
  key: 'nk:sess:api',
  /**  session 过期时间，以毫秒ms为单位计算 。*/
  maxAge: 7200 * 1000,
  /** 自动提交到响应头。(默认是 true) */
  autoCommit: true,
  /** 是否允许重写 。(默认是 true) */
  overwrite: true,
  /** 是否设置HttpOnly，如果在Cookie中设置了"HttpOnly"属性，那么通过程序(JS脚本、Applet等)将无法读取到Cookie信息，这样能有效的防止XSS攻击。  (默认 true) */
  httpOnly: true,
  /** 是否签名。(默认是 true) */
  signed: true,
  /** 是否每次响应时刷新Session的有效期。(默认是 false) */
  rolling: true,
  /** 是否在Session快过期时刷新Session的有效期。(默认是 false) */
  renew: false,
  //默认状态下,koa-session会将信息进行base64序列化后,存在客户端cookie中,使用store可以自定义存储方式
  //store: js.cloneObject(cc.store)
};
// 这个是配合signed属性的签名key
app.keys = [conf.session_keys];
// 处理session
app.use(session(CONFIG, app));

// begin
app.use(async (c, n) => {
  // ignore favicon
  if (c.path === '/favicon.ico') return;

  try {
    await n()
  } catch (err) {

    let fmterr = ''
    if (err.code) {
      fmterr = err
    } else if (typeof err === 'string') {
      fmterr = {
        code: js.rescode.fail,
        msg: err
      }
    } else if (util.types.isNativeError(err)) {
      if (err.status === 401 || err.status === 405) { //jwt权限错误
        fmterr = {
          code: js.rescode.login_fail,
          msg: '用户未登录'
        }
      } else {
        cc.err_uri(err, c)
        fmterr = {
          code: js.rescode.undefined_fail,
          msg: cc.getSystemErrorName(err)
        }
      }
    }

    c.body = fmterr
  }
})

/**********************************************************
 * 登录验证模块
 */
//不验证的路由
const nochecklogin = /^((\/service).)+$|^\/service\/login/ //非/api_开头的路由都不验证
// const nochecklogin = /^\/_test\/authinit|^\/_test\/authsign/ //指定具体路由(/_test/authinit | /_test/authsign)
// //********************************************************
// //jwt登录验证
// app.use(koajwt({
//   secret: cc.conf.jwt_secret
// }).unless({
//   // 登录接口不需要验证
//   path: [nochecklogin]
// }));
// //********************************************************
// session登录验证
// app.use(async (c, n) => {
//   if (!nochecklogin.test(c.url) && !c.session.user) {
//     js.throwObj('用户未登录', js.rescode.login_fail);
//   }
//   await n();
// });


// service_routes
const service_routes = require('./service_routes')
app.use(service_routes.routes(), service_routes.allowedMethods())

// client_routes
const client_routes = require('./client_routes')
app.use(client_routes.routes(), client_routes.allowedMethods())


// test
const test = require('./conCtl_test')
app.use(test.routes(), test.allowedMethods())

//最后use static路径,避免api被拦截
app.use(require('koa-static')(__dirname + '/public'))

// error-handling
app.on('error', (err, ctx) => {
  console.error('server error', err, ctx)
});

module.exports = app